﻿using Txt2Shp4Sharp.geojson;
using Txt2Shp4Sharp.lib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Txt2Shp4Sharp.landm
{
    public class Land 
    {
        //ring标识
        private static int oldRingFlag = 0;

        // 格式版本号
        private String formatVersion;
        // 数据产生单位
        private String dataProduceOrg;
        // 数据产生日期
        private String produceDate;
        // 坐标系
        private String coordinateSystem;
        // 几度分带
        private String degreeNo;
        // 投影类型
        private String projectionType;
        // 计量单位
        private String unit;
        // 带号
        private String degreeNum;
        // 精度
        private String precision;
        // 转换参数
        private String conversionParameter;

        // 地块集合
        private List<Block> blocks;

        public Land()
        {
            this.blocks = new List<Block>();
        }

        public Land(LandHeader header)
        {
            this.formatVersion = header.FormatVersion;
            this.dataProduceOrg = header.DataProduceOrg;
            this.produceDate = header.ProduceDate;
            this.coordinateSystem = header.CoordinateSystem;
            this.degreeNo = header.DegreeNo;//几度分带
            this.projectionType = header.ProjectionType;
            this.unit = header.Unit;
            this.degreeNum = header.DegreeNum;
            this.precision = header.Precision;//精度
            this.conversionParameter = header.ConversionParameter;//精度						

            this.blocks = new List<Block>();
        }


        #region  属性信息

        // 属性集合
        public List<Block> Blocks
        {
            get
            {
                return blocks;
            }
        }

        /// <summary>
        /// 格式版本号
        /// </summary>
        public String FormatVersion
        {
            get
            {
                return formatVersion;
            }
            set
            {
                this.formatVersion = value;
            }
        }
        /// <summary>
        ///  数据产生单位
        /// </summary>
        public String DataProduceOrg
        {
            get
            {
                return dataProduceOrg;
            }
            set
            {
                this.dataProduceOrg = value;
            }
        }
        /// <summary>
        /// 数据产生日期
        /// </summary>
        public String ProduceDate
        {
            get
            {
                return produceDate;
            }
            set
            {
                this.produceDate = value;
            }
        }
        /// <summary>
        /// 坐标系
        /// </summary>
        public String CoordinateSystem
        {
            get
            {
                return coordinateSystem;
            }
            set
            {
                this.coordinateSystem = value;
            }
        }
        /// <summary>
        /// 几度分带
        /// </summary>
        public String DegreeNo
        {
            get
            {
                return degreeNo;
            }
            set
            {
                this.degreeNo = value;
            }
        }
        /// <summary>
        /// 投影类型
        /// </summary>
        public String ProjectionType
        {
            get
            {
                return projectionType;
            }
            set
            {
                this.projectionType = value;
            }
        }
        /// <summary>
        /// 计量单位
        /// </summary>
        public String Unit
        {
            get
            {
                return unit;
            }
            set
            {
                this.unit = value;
            }
        }
        /// <summary>
        /// 带号
        /// </summary>
        public String DegreeNum
        {
            get
            {
                return degreeNum;
            }
            set
            {
                this.degreeNum = value;
            }
        }
        /// <summary>
        /// 精度
        /// </summary>
        public String Precision
        {
            get
            {
                return precision;
            }
            set
            {
                this.precision = value;
            }
        }
        /// <summary>
        /// 转换参数
        /// </summary>
        public String ConversionParameter
        {
            get
            {
                return conversionParameter;
            }
            set
            {
                this.conversionParameter = value;
            }
        }

        #endregion

        /// <summary>
        /// 读取标准图形坐标串txt文件（清华三维导出，fme提取转换）
        /// </summary>
        /// <param name="filePath">txt物理路径</param>
        /// <returns></returns>
        public static Land readTxtFile(String filePath, String encoding)
        {
            oldRingFlag = 0;
            Land land = new Land();
            try
            {
                Block block = null;
                Ring ring = null;

                if (File.Exists(filePath))
                {   
                    //文件名
                    String fileNameWithNoExt = System.IO.Path.GetFileNameWithoutExtension(filePath);
                    //读取txt文件
                    using (StreamReader reader = new StreamReader(File.Open(filePath, FileMode.Open), Encoding.GetEncoding(encoding)))
                    {
                        //行数
                        int lineNum = 0;
                        //遍历每一行line，很重要
                        String lineTxt = null;
                        while ((lineTxt = reader.ReadLine()) != null && lineTxt != string.Empty)
                        {
                            lineNum++;

                            //1、land txt 的基本信息（格式版本号=1.0版本）
                            if (lineTxt.IndexOf("=") != -1)
                            {
                                Char[] charSequences = new Char[] { '=' };
                                String[] line = lineTxt.Split(charSequences);

                                if ((line[0] != null) && (line[0] == "格式版本号") && line.Length > 1)
                                {
                                    land.FormatVersion = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "数据产生单位") && line.Length > 1)
                                {
                                    land.DataProduceOrg = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "数据产生日期") && line.Length > 1)
                                {
                                    land.ProduceDate = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "坐标系") && line.Length > 1)
                                {
                                    land.CoordinateSystem = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "几度分带") && line.Length > 1)
                                {
                                    land.DegreeNo = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "投影类型") && line.Length > 1)
                                {
                                    land.ProjectionType = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "计量单位") && line.Length > 1)
                                {
                                    land.Unit = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "带号") && line.Length > 1)
                                {
                                    land.DegreeNum = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "精度") && line.Length > 1)
                                {
                                    land.Precision = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "转换参数") && line.Length > 1)
                                {
                                    land.ConversionParameter = line[1];
                                }
                            }
                            else
                            {
                                //2、新地块block 信息   1038,59.1068,13,13,面,,,地类编码,@
                                //通过@来分割
                                if (lineTxt.IndexOf("@") != -1)
                                {
                                    //新建地块---同时新建地块环
                                    block = new Block();
                                    ring = new Ring();
                                    ring.RingId = 1;
                                    oldRingFlag = 1;

                                    //对每一行按照“，”号分割
                                    Char[] charSequences = new Char[] { ',' };
                                    String[] line = lineTxt.Split(charSequences);
                                    if (!StringUtil.isNullOrEmpty(line[0]))
                                    {
                                        int jzds = 0;
                                        int.TryParse(line[0], out jzds);
                                        block.DKAttrs.Add("jzds", jzds);
                                        block.Jzds = jzds;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[1]))
                                    {
                                        Double dkmj = 0.0;
                                        Double.TryParse(line[1], out dkmj);
                                        block.DKAttrs.Add("dkmj", dkmj);
                                        block.Dkmj = dkmj;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[2]))
                                    {
                                        String dkbh = line[2];
                                        block.DKAttrs.Add("dkbh", dkbh);
                                        block.Dkbh = dkbh;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[3]))
                                    {
                                        String dkmc = line[3];
                                        block.DKAttrs.Add("dkmc", dkmc);
                                        block.Dkmc = dkmc;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[4]))
                                    {
                                        String jltxsx = line[4];
                                        block.DKAttrs.Add("jltxsx", jltxsx);
                                        block.Jltxsx = jltxsx;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[5]))
                                    {
                                        String tfh = line[5];
                                        block.DKAttrs.Add("tfh", tfh);
                                        block.Tfh = tfh;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[6]))
                                    {
                                        String dkyt = line[6];
                                        block.DKAttrs.Add("dkyt", dkyt);
                                        block.Dkyt = dkyt;
                                    }

                                    block.DKRings.Add(ring);
                                    if( !block.DKAttrs.ContainsKey("bz") ){
                                        block.DKAttrs.Add("bz",fileNameWithNoExt);
                                    }
                                    
                                    land.Blocks.Add(block);
                                }
                                else
                                {
                                    //分割数据行的数据 J2,1,3297731.838,36371740.460
                                    if (lineTxt.IndexOf("J") != -1)
                                    {
                                        Char[] charSequences = new Char[] { ',' };
                                        String[] attrs = lineTxt.Split(charSequences);

                                        //新环标识							
                                        int newringFlag = int.Parse(attrs[1]);
                                        if (newringFlag != oldRingFlag) {
                                            ring = new Ring();
                                            ring.RingId = newringFlag;

                                            block.DKRings.Add(ring);
                                            //这个很关键
                                            oldRingFlag = newringFlag;
                                        }

                                        JzdPoint point = new JzdPoint();
                                        //注意，txt中x为36-xxx，
                                        if (!StringUtil.isNullOrEmpty(attrs[2]))
                                        {
                                            double y = 0.0;
                                            Double.TryParse(attrs[2], out y);
                                            point.Y = y;
                                        }
                                        if (!StringUtil.isNullOrEmpty(attrs[3]))
                                        {
                                            String xstr = attrs[3];
                                            if (attrs[3].IndexOf('|') != -1)
                                            {
                                                xstr = attrs[3].Substring(0, attrs[3].IndexOf('|'));
                                            }
                                            double x = 0.0;
                                            Double.TryParse(xstr, out x);
                                            point.X = x;
                                        }

                                        ring.JzdPoints.Add(point);
                                    }
                                }
                            }
                        }
                        reader.Close();
                    }
                }
                else
                {
                    System.Console.WriteLine("找不到指定的Txt文件");
                }
            }
            catch (Exception ex)
            {
                string errMsg = ex.Message;
                System.Console.WriteLine(String.Format("--->读取文件内容出错: 原因{0}", errMsg));
            }
            return land;
        }

 
        /// <summary>
        ///   读取txt生成一个land对象: 通过Y坐标的前2位进行自动判断，自动映射到degreeNum中
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static Land readTxtFile2(String filePath, String encoding)
        {
            oldRingFlag = 0;
            Boolean degreeNumFlag = true;
            Land land = new Land();
            try
            {

                Block block = null;
                Ring ring = null;

                if (File.Exists(filePath))
                {
                    //文件名
                    String fileNameWithNoExt = System.IO.Path.GetFileNameWithoutExtension(filePath);
                    //读取txt文件
                    using (StreamReader reader = new StreamReader(File.Open(filePath, FileMode.Open), Encoding.GetEncoding(encoding)))
                    {
                        //行数
                        int lineNum = 0;
                        //遍历每一行line，很重要
                        String lineTxt = null;
                        while ((lineTxt = reader.ReadLine()) != null && lineTxt != string.Empty)
                        {
                            lineNum++;

                            //1、land txt 的基本信息（格式版本号=1.0版本）
                            if (lineTxt.IndexOf("=") != -1)
                            {
                                Char[] charSequences = new Char[] { '=' };
                                String[] line = lineTxt.Split(charSequences);

                                if ((line[0] != null) && (line[0] == "格式版本号") && line.Length > 1)
                                {
                                    land.FormatVersion = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "数据产生单位") && line.Length > 1)
                                {
                                    land.DataProduceOrg = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "数据产生日期") && line.Length > 1)
                                {
                                    land.ProduceDate = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "坐标系") && line.Length > 1)
                                {
                                    land.CoordinateSystem = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "几度分带") && line.Length > 1)
                                {
                                    land.DegreeNo = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "投影类型") && line.Length > 1)
                                {
                                    land.ProjectionType = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "计量单位") && line.Length > 1)
                                {
                                    land.Unit = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "带号") && line.Length > 1)
                                {
                                    land.DegreeNum = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "精度") && line.Length > 1)
                                {
                                    land.Precision = line[1];
                                }
                                else if ((line[0] != null) && (line[0] == "转换参数") && line.Length > 1)
                                {
                                    land.ConversionParameter = line[1];
                                }
                            }
                            else
                            {
                                //2、新地块block 信息   1038,59.1068,13,13,面,,,地类编码,@
                                //通过@来分割
                                if (lineTxt.IndexOf("@") != -1)
                                {
                                    //新建地块---同时新建地块环
                                    block = new Block();
                                    ring = new Ring();
                                    ring.RingId = 1;
                                    oldRingFlag = 1;

                                    //对每一行按照“，”号分割
                                    Char[] charSequences = new Char[] { ',' };
                                    String[] line = lineTxt.Split(charSequences);
                                    if (!StringUtil.isNullOrEmpty(line[0]))
                                    {
                                        int jzds = 0;
                                        int.TryParse(line[0], out jzds);
                                        block.DKAttrs.Add("jzds", jzds);
                                        block.Jzds = jzds;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[1]))
                                    {
                                        Double dkmj = 0.0;
                                        Double.TryParse(line[1], out dkmj);
                                        block.DKAttrs.Add("dkmj", dkmj);
                                        block.Dkmj = dkmj;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[2]))
                                    {
                                        String dkbh = line[2];
                                        block.DKAttrs.Add("dkbh", dkbh);
                                        block.Dkbh = dkbh;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[3]))
                                    {
                                        String dkmc = line[3];
                                        block.DKAttrs.Add("dkmc", dkmc);
                                        block.Dkmc = dkmc;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[4]))
                                    {
                                        String jltxsx = line[4];
                                        block.DKAttrs.Add("jltxsx", jltxsx);
                                        block.Jltxsx = jltxsx;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[5]))
                                    {
                                        String tfh = line[5];
                                        block.DKAttrs.Add("tfh", tfh);
                                        block.Tfh = tfh;
                                    }
                                    if (!StringUtil.isNullOrEmpty(line[6]))
                                    {
                                        String dkyt = line[6];
                                        block.DKAttrs.Add("dkyt", dkyt);
                                        block.Dkyt = dkyt;
                                    }

                                    block.DKRings.Add(ring);
                                    if (!block.DKAttrs.ContainsKey("bz"))
                                    {
                                        block.DKAttrs.Add("bz", fileNameWithNoExt);
                                    }

                                    land.Blocks.Add(block);
                                }
                                else
                                {
                                    //分割数据行的数据 J2,1,3297731.838,36371740.460
                                    if (lineTxt.IndexOf("J") != -1)
                                    {
                                        Char[] charSequences = new Char[] { ',' };
                                        String[] attrs = lineTxt.Split(charSequences);

                                        //新环标识							
                                        int newringFlag = int.Parse(attrs[1]);
                                        if (newringFlag != oldRingFlag)
                                        {
                                            ring = new Ring();
                                            ring.RingId = newringFlag;

                                            block.DKRings.Add(ring);
                                            //这个很关键
                                            oldRingFlag = newringFlag;
                                        }

                                        JzdPoint point = new JzdPoint();
                                        //注意，txt中x为36-xxx，
                                        if (!StringUtil.isNullOrEmpty(attrs[2]))
                                        {
                                            double y = 0.0;
                                            Double.TryParse(attrs[2], out y);
                                            point.Y = y;
                                        }
                                        if (!StringUtil.isNullOrEmpty(attrs[3]))
                                        {
                                            String xstr = attrs[3];
                                            if (attrs[3].IndexOf('|') != -1)
                                            {
                                                xstr = attrs[3].Substring(0, attrs[3].IndexOf('|'));
                                            }
                                            double x = 0.0;
                                            Double.TryParse(xstr, out x);
                                            point.X = x;

                                            //很重要，判断投影度带,不支持无度带的数据处理
                                            int length = attrs[3].Length;
                                            //是否带有小数点
                                            int indexOfDot = attrs[3].IndexOf('.');
                                            if (indexOfDot == -1)
                                            {
                                                if (degreeNumFlag == true && attrs[3].Substring(0, length - 1).Length == 8)
                                                {
                                                    String degreeNoStr = attrs[3].Substring(0, 2);
                                                    land.DegreeNum = degreeNoStr;
                                                    degreeNumFlag = false;
                                                }
                                                else if (degreeNumFlag == true && attrs[3].Substring(0, indexOfDot).Length == 5)
                                                {
                                                    land.DegreeNum = "cqdl";
                                                    degreeNumFlag = false;
                                                }
                                            }
                                            else
                                            {
                                                if (degreeNumFlag == true && attrs[3].Substring(0, indexOfDot).Length == 8)
                                                {
                                                    String degreeNoStr = attrs[3].Substring(0, 2);
                                                    land.DegreeNum = degreeNoStr;
                                                    degreeNumFlag = false;
                                                }
                                                else if (degreeNumFlag == true && attrs[3].Substring(0, indexOfDot).Length == 5)
                                                {
                                                    land.DegreeNum = "cqdl";
                                                    degreeNumFlag = false;
                                                }
                                            }
                                        }

                                        ring.JzdPoints.Add(point);
                                    }
                                }
                            }
                        }
                        reader.Close();
                    }
                }
                else
                {
                    System.Console.WriteLine("找不到指定的Txt文件");
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("读取文件内容出错: " + e.Message);
            }
            return land;
        }

        public String toTxtFile(String path, String txtName)
        {
            String encoding = "GBK";
            String txtFileName = path + "\\" + txtName;
            // 输出land中内容到txt文件中
            if (File.Exists(txtFileName)){
                File.Delete(txtFileName);
            }

            using (StreamWriter pw = new StreamWriter(File.Open(txtFileName, FileMode.OpenOrCreate, FileAccess.Write), Encoding.GetEncoding(encoding)))
            {
                //基本信息
                pw.WriteLine("[属性描述]");
                pw.WriteLine("格式版本号=" + this.FormatVersion);
                pw.WriteLine("数据产生单位=" + this.DataProduceOrg);
                pw.WriteLine("数据产生日期=" + this.ProduceDate);
                pw.WriteLine("坐标系=" + this.CoordinateSystem);
                pw.WriteLine("几度分带=" + this.DegreeNo);
                pw.WriteLine("投影类型=" + this.ProjectionType);
                pw.WriteLine("计量单位=" + this.Unit);
                pw.WriteLine("带号=" + this.DegreeNum);
                pw.WriteLine("精度=" + this.Precision);
                pw.WriteLine("转换参数=" + this.ConversionParameter);

                //坐标序列
                pw.WriteLine("[地块坐标]");

                int blockCount = this.Blocks.Count;
                for (int i = 0; i < blockCount; i++)
                {
                    Block block = this.Blocks[i];
                    int ringCount = block.DKRings.Count;

                    //获取某个地块block的界址点数
                    int jzdCount = 0;
                    for (int j = 0; j < ringCount; j++)
                    {
                        Ring ring = block.DKRings[j];
                        int ringJzdCount = ring.JzdPoints.Count;

                        jzdCount += ringJzdCount;
                    }

                    int bhIndex = i + 1;
                    String dkmj = String.Format("%.4f", block.Dkmj);
                    // String dkbh = block.getDkbh();
                    String dkbh = "地块" + bhIndex;
                    String dkmc = block.Dkmc;
                    String jltxsx = block.Jltxsx;
                    String tfh = block.Tfh;
                    String dkyt = block.Dkyt;

                    // 坐标序列台头
                    // 界址点数,地块面积,地块编号,地块名称,记录图形属性(点、线、面),图幅号,地块用途,地类编码,@
                    String blockHeader = String.Format("%s,%s,%s,%s,%s,%s,%s,%s,%s", jzdCount, dkmj, dkbh,
                            dkmc, jltxsx, tfh, dkyt, "地类编码", "@");
                    pw.WriteLine(blockHeader);

                    for (int j = 0; j < ringCount; j++)
                    {
                        Ring ring = block.DKRings[j];
                        int pointCount = ring.JzdPoints.Count;

                        int ringIndex = j + 1;
                        for (int k = 0; k < pointCount; k++)
                        {
                            JzdPoint pt = ring.JzdPoints[k];
                            String y = String.Format("%.3f", pt.Y);
                            String x = String.Format("%.3f", pt.X);

                            int jzdIndex = k + 1;
                            String jzdLabel = "J" + jzdIndex;
                            String jzdLine = String.Format("%s,%s,%s,%s", jzdLabel, ringIndex, y, x);
                            //打印具体坐标点
                            pw.WriteLine(jzdLine);
                        }
                    }
                }
                pw.Flush();
                pw.Close();
            }

            return txtFileName;
        }

        public String toJsonStr()
        {
            GeoJson geoJson = new GeoJson();
            try
            {
                List<GeoJsonFeature> features = new List<GeoJsonFeature>();
                //坐标序列
                int blockCount = this.Blocks.Count;
                for (int i = 0; i < blockCount; i++)
                {
                    Block block = this.Blocks[i];
                    int ringCount = block.DKRings.Count;

                    GeoJsonFeature fea = new GeoJsonFeature();

                    //geo.setCoordinates(coordinates);
                    //获取某个地块block的界址点数
                    int jzdCount = 0;
                    for (int ii = 0; ii < ringCount; ii++)
                    {
                        Ring ring = block.DKRings[ii];
                        int ringJzdCount = ring.JzdPoints.Count;

                        jzdCount += ringJzdCount;
                    }

                    //属性信息
                    Dictionary<String, Object> properties = new Dictionary<String, Object>();
                    int bhIndex = i + 1;
                    String dkmj = String.Format("%.4f", block.Dkmj);
                    // String dkbh = block.getDkbh();
                    String dkbh = "地块" + bhIndex;
                    String dkmc = block.Dkmc;
                    String jltxsx = block.Jltxsx;
                    String tfh = block.Tfh;
                    String dkyt = block.Dkyt;
                    properties.Add("dkbh", dkbh);
                    properties.Add("dkmc", dkmc);
                    properties.Add("jltxsx", jltxsx);
                    properties.Add("tfh", tfh);
                    properties.Add("dkyt", dkyt);
                    properties.Add("dkmj", dkmj);

                    fea.FeaType="feature";
                    fea.GeoProperties=properties;

                    //图形坐标串
                    GeoJsonGeometry geo = new GeoJsonGeometry();
                    geo.Type="Polygon";
                    double[][][] coordinates = new double[ringCount][][];
                    for (int j = 0; j < ringCount; j++)
                    {
                        Ring ring = block.DKRings[j];

                        int pointCount = ring.JzdPoints.Count;
                        double[][] pointCoords = new double[pointCount][];
                        for (int k = 0; k < pointCount; k++)
                        {
                            JzdPoint pt = ring.JzdPoints[k];
                            double x = 0.0;
                            Double.TryParse(String.Format("%.3f", pt.X),out x);
                            double y = 0.0;
                            Double.TryParse(String.Format("%.3f", pt.Y),out y);

                            double[] coords = new double[2];
                            coords[0] = x;
                            coords[1] = y;

                            pointCoords[k] = coords;
                        }
                        coordinates[j] = pointCoords;
                    }

                    geo.Coordinates=coordinates;
                    fea.Geometry=geo;
                    features.Add(fea);
                }

                geoJson.GeoFeatures=features;
                geoJson.Type = "FeatureCollection";
            }
            catch (Exception ex)
            {
                string errMsg = ex.Message;
                System.Console.WriteLine(errMsg);
            }

            return JsonConvert.SerializeObject(geoJson);
        }

    }
}
